package GtEngine

import (
	"container/list"
	"net"
)

import (
	. "tksLog"
	. "tksStatic"
	. "tksTcp"
	. "tksUint"
)

type ServerInfo struct {
	Cleint *ClientInfo
	Cnt    uint32
	Id     uint32
	Cmds   *list.List
}

type ServersInfo map[uint32]*ServerInfo

var CmdServers map[uint16]ServersInfo //CmdServers[cmd]=ServerInfo
var IdServers map[uint32]*ServerInfo  //IdServers[serverid]=ServerInfo

func init() {
	CmdServers = make(map[uint16]ServersInfo)
	IdServers = make(map[uint32]*ServerInfo)
}

func sendRsp(conn net.Conn, from uint32, to uint32, seq uint16, cmd uint16, ret Ret) {
	var rsp ServerConnectGateRsp
	rsp.R = ret
	data, _ := MsgToBuf(rsp)
	Debug("send rsp, cmd: %d, data: %s", cmd, string(data))
	SendBuffer(conn, from, to, seq, cmd, data)
}

func registerServer(serverid uint32, cmds []interface{}, conn net.Conn) *ServerInfo {
	client := FindGateClientByAddr(conn.RemoteAddr().String())
	if client == nil {
		return nil
	}

	info := new(ServerInfo)
	info.Cleint = client
	info.Cnt = 0
	info.Id = serverid
	info.Cmds = list.New()
	//
	IdServers[serverid] = info
	//
	for _, cmd := range cmds {
		i16 := cmd.(uint16)
		cmdinfo, ok := CmdServers[i16]
		if !ok {
			CmdServers[i16] = make(map[uint32]*ServerInfo)
		}
		cmdinfo[serverid] = info
		info.Cmds.PushBack(i16)
	}

	return info
}

func FindServerById(serverid uint32) *ServerInfo {
	info, ok := IdServers[serverid]
	if ok {
		return info
	} else {
		return nil
	}
}

func FindServerByCmd(cmd uint16) *ServerInfo {
	// info, ok := CmdServers[cmd]
	// if ok {
	// 	return info
	// } else {
	// 	return nil
	// }

	//todo
	return nil
}

func ServerConnect(conn net.Conn, from uint32, to uint32, seq uint16, buf []byte) {
	Debug("recv server connset from %s %u, info: %s", conn.RemoteAddr().String(), from, string(buf))
	json, err := BufToMsg(buf)
	if err != nil {
		sendRsp(conn, to, from, seq, CmdServerConnectGateRsp, RetMsgFormatError)
		return
	}
	id, _ := json.Get("Id").Int()
	cmds, _ := json.Get("Cmds").Array()
	info := FindServerById(uint32(id))
	if info != nil {
		delete(IdServers, uint32(id))
		for e := info.Cmds.Front(); e != nil; e = e.Next() {
			delete(CmdServers[e.Value.(uint16)], uint32(id))
		}
	}
	registerServer(uint32(id), cmds, conn)
	sendRsp(conn, to, from, seq, CmdServerConnectGateRsp, RetSucc)
}
